package com.virgo.demo.system.service.impl;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.virgo.common.exception.IApplicationException;
import com.virgo.common.utils.ICommonUtils;
import com.virgo.demo.system.domain.AdminRoleDo;
import com.virgo.demo.system.domain.SystemResourceDo;
import com.virgo.demo.system.domain.bo.SystemResourceBo;
import com.virgo.demo.system.mapper.AdminRoleMapper;
import com.virgo.demo.system.mapper.SystemResourceMapper;
import com.virgo.demo.system.service.SystemResourceService;
import com.virgo.web.utils.IRequestUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class SystemResourceServiceImpl extends ServiceImpl<SystemResourceMapper, SystemResourceDo> implements SystemResourceService {

	private final SystemResourceMapper systemResourceMapper;

	private final AdminRoleMapper adminRoleMapper;

	/**
	 * 根据key查找
	 * @param rightKey String
	 * @return SystemResourceDo
	 */
	@Override
	public SystemResourceDo loadByRightKey(String rightKey) {
		LambdaQueryWrapper<SystemResourceDo> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(SystemResourceDo::getRightKey, rightKey);
		queryWrapper.last(" limit 1 ");
		return getOne(queryWrapper);
	}

	/**
	 * 编辑权限节点
	 * @param systemResourceBo SystemResourceBo
	 */
	@Override
	public void saveSystemResource(SystemResourceBo systemResourceBo) {
		SystemResourceDo exist = loadByRightKey(systemResourceBo.getRightKey());
		SystemResourceDo systemResourceDo = new SystemResourceDo();
		BeanUtils.copyProperties(systemResourceBo,systemResourceDo);
		if (!ObjectUtils.isEmpty(exist) && !exist.getId().equals(systemResourceDo.getId())) {
			throw new IApplicationException("权限节点-" + systemResourceDo.getRightKey() + "已存在");
		}
		if (ObjectUtils.isEmpty(systemResourceDo.getId()) || systemResourceDo.getId().compareTo(0L) < 1) {
			save(systemResourceDo);
			return;
		}
		updateById(systemResourceDo);
	}

	/**
	 * 删除权限节点
	 * @param ids String
	 */
	@Override
	public void deleteSystemResource(String ids) {
		List<Long> idList = Arrays.asList(ICommonUtils.stringToArray(ids, ","));
		LambdaQueryWrapper<SystemResourceDo> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.in(SystemResourceDo::getParentId,idList);
		long num = count(queryWrapper);
		if (num > 0L) {
			throw new IApplicationException("所选节点存在下级，不能删除");
		}
		removeByIds(idList);
	}

	/**
	 * 权限节点树
	 * @return List<Tree < Long>>
	 */
	@Override
	public List<Tree<Long>> resourceTree(HttpServletRequest request) {
		LambdaQueryWrapper<SystemResourceDo> queryWrapper = new LambdaQueryWrapper<>();
        String isMenu = IRequestUtils.getString(request,"isMenu","");
        if ("1".equals(isMenu)) {
            queryWrapper.eq(SystemResourceDo::getIsMenu,1);
        }
		List<SystemResourceDo> systemResourceDos = systemResourceMapper.selectList(queryWrapper);
		if (ObjectUtils.isEmpty(systemResourceDos)) {
			return List.of();
		}
		TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
		treeNodeConfig.setIdKey("id");
		treeNodeConfig.setNameKey("name");
		treeNodeConfig.setParentIdKey("parentId");
		treeNodeConfig.setChildrenKey("children");
		treeNodeConfig.setDeep(null);
		return TreeUtil.build(systemResourceDos, 0L, treeNodeConfig, (treeNode, tree) -> {
			tree.setId(treeNode.getId());
			tree.setParentId(treeNode.getParentId());
			tree.setName(treeNode.getName());
			tree.putExtra("rightKey",treeNode.getRightKey());
			tree.putExtra("isMenu",treeNode.getIsMenu());
		});
	}

    /**
     * 菜单权限数据
     * @param roleId Long
     * @return List<String>
     */
    @Override
    public List<String> menuData(Long roleId) {
        LambdaQueryWrapper<SystemResourceDo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SystemResourceDo::getIsMenu,1);
        queryWrapper.select(SystemResourceDo::getRightKey);
        List<SystemResourceDo> systemResourceDos = systemResourceMapper.selectList(queryWrapper);
        if (ObjectUtils.isEmpty(systemResourceDos)) {
            return List.of();
        }
        List<String> rightKeyList = systemResourceDos.stream().map(SystemResourceDo::getRightKey).distinct().toList();
        if (roleId.compareTo(0L) > 0) {
            //非超管
            AdminRoleDo adminRoleDo = adminRoleMapper.selectById(roleId);
            if (ObjectUtils.isEmpty(adminRoleDo) || adminRoleDo.getStatus().equals(0) || ObjectUtils.isEmpty(adminRoleDo.getRightsList())) {
                return List.of();
            }
            List<String> result = new ArrayList<>();
            List<String> rightList = Arrays.asList(adminRoleDo.getRightsList().split(","));
            for (String rightKey : rightKeyList) {
                if (rightList.contains(rightKey)) {
                    result.add(rightKey);
                }
            }
            return result;
        }
        return rightKeyList;
    }

    /**
     * 按钮权限数据
     * @param roleId Long
     * @return List<String>
     */
    @Override
    public HashMap<String, Object> buttonData(Long roleId) {
        LambdaQueryWrapper<SystemResourceDo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SystemResourceDo::getIsMenu,1);
        queryWrapper.gt(SystemResourceDo::getParentId,0L);
        queryWrapper.select(SystemResourceDo::getId,SystemResourceDo::getRightKey);
        List<SystemResourceDo> systemResourceDos = systemResourceMapper.selectList(queryWrapper);
        if (ObjectUtils.isEmpty(systemResourceDos)) {
            return new HashMap<>();
        }
        List<Long> menuIdList = systemResourceDos.stream().map(SystemResourceDo::getId).distinct().toList();
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SystemResourceDo::getIsMenu,0);
        queryWrapper.in(SystemResourceDo::getParentId,menuIdList);
        queryWrapper.select(SystemResourceDo::getRightKey,SystemResourceDo::getParentId);
        List<SystemResourceDo> buttonList = systemResourceMapper.selectList(queryWrapper);
        HashMap<String, Object> result = new HashMap<>();
        List<SystemResourceDo> buttonData = new ArrayList<>();
        if (roleId.compareTo(0L) > 0) {
            //非超管
            AdminRoleDo adminRoleDo = adminRoleMapper.selectById(roleId);
            if (ObjectUtils.isEmpty(adminRoleDo) || adminRoleDo.getStatus().equals(0) || ObjectUtils.isEmpty(adminRoleDo.getRightsList())) {
                return result;
            }
            List<String> userRightKeyList = Arrays.asList(adminRoleDo.getRightsList().split(","));
            for (SystemResourceDo systemResourceDo : buttonList) {
                if (userRightKeyList.contains(systemResourceDo.getRightKey())) {
                    buttonData.add(systemResourceDo);
                }
            }
        } else {
            buttonData = buttonList;
        }
        Map<Long, List<SystemResourceDo>> buttonMapList = Optional.ofNullable(buttonData).orElse(new ArrayList<>()).stream()
            .collect(Collectors.groupingBy(SystemResourceDo::getParentId));
        for (SystemResourceDo systemResourceDo : systemResourceDos) {
            List<SystemResourceDo> dos = buttonMapList.getOrDefault(systemResourceDo.getId(), new ArrayList<>());
            List<String> rightList = dos.stream().map(SystemResourceDo::getRightKey).distinct().toList();
            result.put(systemResourceDo.getRightKey(),rightList);
        }
        return result;
    }
}